package com.jia.train.seat.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jia.train.global.enums.BusinessEnum;
import com.jia.train.global.exception.BusinessException;
import com.jia.train.global.page.PageResponse;
import com.jia.train.global.utils.SnowIdUtil;
import com.jia.train.seat.entity.Trips;
import com.jia.train.seat.entity.TripsExample;
import com.jia.train.seat.mapper.TripsMapper;
import com.jia.train.seat.request.TripsQueryRequest;
import com.jia.train.seat.request.TripsSaveRequest;
import com.jia.train.seat.response.TripsQueryResponse;
import com.jia.train.seat.response.TripsSaveResponse;
import com.jia.train.seat.service.TripsService;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;

@Service
public class TripsServiceImpl implements TripsService {

    @Resource
    private TripsMapper tripsMapper;

    @Resource
    private TransactionTemplate transactionTemplate;

    public static final Logger logger = LoggerFactory.getLogger(TripsServiceImpl.class);


    @Override
    public TripsSaveResponse insert(TripsSaveRequest request) {
        Trips trips = BeanUtil.copyProperties(request, Trips.class);
        DateTime now = DateTime.now();
        String start = request.getStart();
        String end = request.getEnd();
        String code = request.getCode();
        if (ObjectUtil.isNotEmpty(start)) {
            trips.setStartPinyin(PinyinUtil.getPinyin(start, ""));
        }
        if (ObjectUtil.isNotEmpty(end)) {
            trips.setEndPinyin(PinyinUtil.getPinyin(end, ""));
        }
        if (ObjectUtil.isEmpty(trips.getId())) {
            if (getTripsCount(code) > 0) {
                throw new BusinessException(BusinessEnum.TRAIN_NUMBER_ALREADY_EXISTS);
            }
            trips.setId(SnowIdUtil.getLongSnowNextId());
            trips.setCreateTime(now);
            tripsMapper.insert(trips);
        } else {
            trips.setUpdateTime(now);
            tripsMapper.updateByPrimaryKeySelective(trips);
        }

        return BeanUtil.copyProperties(trips, TripsSaveResponse.class);
    }

    @Override
    public PageResponse<TripsQueryResponse> selectPage(TripsQueryRequest request) {

        TripsExample tripsExample = new TripsExample();

        // 构造分页
        PageHelper.startPage(request.getPage(), request.getSize());
        List<Trips> tripsList = tripsMapper.selectByExample(tripsExample);
        PageInfo<Trips> pageInfo = new PageInfo<>(tripsList);

        List<TripsQueryResponse> list = BeanUtil.copyToList(tripsList, TripsQueryResponse.class);

        PageResponse<TripsQueryResponse> pageResponse = new PageResponse<>();
        pageResponse.setTotal(pageInfo.getTotal());
        pageResponse.setList(list);
        return pageResponse;
    }

    @Override
    // 一级缓存 可以使用 @Transactional 和 TransactionTemplate 代替
    // 原理是  保证sqlSession的唯一性
    public List<TripsQueryResponse> selectList() {
        TripsExample tripsExample = new TripsExample();
        tripsExample.setOrderByClause("code asc");
        return transactionTemplate.execute(callback -> {
            try {
                List<Trips> tripsList = tripsMapper.selectByExample(tripsExample);
                logger.info("再查一次");
                tripsList = tripsMapper.selectByExample(tripsExample);
                return BeanUtil.copyToList(tripsList, TripsQueryResponse.class);
            } catch (Exception e) {
                callback.setRollbackOnly();
                throw new RuntimeException(e.getMessage());
            }
        });
    }

    @Override
    public void deleteTrips(Long id) {
        tripsMapper.deleteByPrimaryKey(id);
    }

    private long getTripsCount(String code) {
        TripsExample TripsExample = new TripsExample();
        TripsExample.Criteria criteria = TripsExample.createCriteria();
        criteria.andCodeEqualTo(code);
        return tripsMapper.countByExample(TripsExample);
    }
}
